package com.cjm.one.custom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cjm.one.common.constant.SecurityConstants;
import com.cjm.one.common.utils.TimeRangeUtils;
import com.cjm.one.custom.mapper.CustomerInfoMapper;
import com.cjm.one.custom.mapper.CustomerLoginLogMapper;
import com.cjm.one.custom.service.UserStatsService;
import com.cjm.one.model.custom.dto.UserChartItem;
import com.cjm.one.model.custom.dto.UserStatsDTO;
import com.cjm.one.model.custom.entity.CustomerInfo;
import com.cjm.one.model.custom.entity.CustomerLoginLog;
import com.cjm.one.model.order.dto.TimeRange;
import com.cjm.one.order.client.OrderInfoClient;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserStatsServiceImpl implements UserStatsService {
    @Resource
    private  CustomerInfoMapper customerInfoMapper;
    @Resource
    private CustomerLoginLogMapper loginLogMapper;

    @Resource
    private OrderInfoClient orderInfoClient;

    // 添加缓存注解提升性能
    @Cacheable(value = "userStats", key = "#timeRange + '-summary'")
    @Override
    public Map<String, Object> getUserSummary(String timeRange) {
        TimeRange currentRange = TimeRangeUtils.parseTimeRange(timeRange);
        TimeRange compareRange = TimeRangeUtils.getCompareRange(timeRange);

        UserStatsDTO current = buildStats(currentRange);
        UserStatsDTO compare = buildStats(compareRange);
        current.calculateGrowthRates(compare);

        // 补充周环比数据
        return Map.of(
                "indicators", List.of(
                        buildIndicator("新增用户", current.getNewUsers(), current.getNewUserGrowthRate(), "人"),
                        buildIndicator("活跃用户", current.getActiveUsers(), current.getActiveUserGrowthRate(), "DAU"),
                        buildIndicator("付费用户", current.getPaidUsers(), current.getPaidUserGrowthRate(), "ARPU"),
                        buildIndicator("留存率", current.getRetentionRate(), BigDecimal.ZERO, "%")
                )
        );
    }

    // 趋势接口支持多维度查询
    @Cacheable(value = "userStats", key = "#timeRange + '-chart'")
    @Override
    public List<UserChartItem> getUserChartData(String timeRange) {
        TimeRange range = TimeRangeUtils.parseTimeRange(timeRange);
        String format = getDateFormat(timeRange);

        List<UserChartItem> items = customerInfoMapper.selectTrendData(range.getStartTime(), range.getEndTime(), format);

        // 补充空日期数据
        return fillEmptyDates(items, range, format);
    }

    private Map<String, Object> buildIndicator(String title, Object value,
                                               BigDecimal rate, String unit) {
        return Map.of(
                "title", title,
                "value", value,
                "rate", rate.setScale(1, RoundingMode.HALF_UP),
                "unit", unit,
                "color", rate.compareTo(BigDecimal.ZERO) >= 0 ? "#67C23A" : "#F56C6C"
        );
    }

    private UserStatsDTO buildStats(TimeRange range) {
        return new UserStatsDTO()
                .setNewUsers(countNewUsers(range))
                .setActiveUsers(countActiveUsers(range))
                .setPaidUsers(countPaidUsers(range))
                .setRetentionRate(calculateRetention(range));
    }

    // 统计新增用户（排除测试账号）
    private Long countNewUsers(TimeRange range) {
        return customerInfoMapper.selectCount(new LambdaQueryWrapper<CustomerInfo>()
                .between(CustomerInfo::getCreateTime, range.getBeginTime(), range.getEndTime())
                .eq(CustomerInfo::getIsDeleted, 0)
                .notLike(CustomerInfo::getNickname, "测试%"));
    }

    // 统计活跃用户（DAU）
    private Long countActiveUsers(TimeRange range) {
        return loginLogMapper.countActiveUsers(range.getStartTime(), range.getEndTime());
    }

    // 统计有效付费用户
    private Long countPaidUsers(TimeRange range) {
        Long data = orderInfoClient.countPaidUsers(range.getBeginTime(), range.getEndTime(), SecurityConstants.INNER).getData();
        if (data == null) return 0L;
        return data;
    }

    // 计算7日留存率
    private BigDecimal calculateRetention(TimeRange range) {
        LocalDateTime retentionStart = range.getStartTime().plusDays(7); // 注册日+7天开始检测
        LocalDateTime retentionEnd = range.getEndTime().plusDays(7);     // 注册日+7天结束检测
        // 计算注册时间窗口
        LocalDateTime registerStart = range.getStartTime();
        LocalDateTime registerEnd = range.getEndTime();

        // 查询注册用户总数
        Long totalUsers = customerInfoMapper.selectCount(
                new LambdaQueryWrapper<CustomerInfo>()
                        .between(CustomerInfo::getCreateTime, registerStart, registerEnd)
                        .eq(CustomerInfo::getIsDeleted, 0)
        );
        if (totalUsers == 0) return BigDecimal.ZERO;

        // 查询留存用户数（使用修正后的SQL）
        Integer retainedUsers = loginLogMapper.selectRetainedUsers(
                registerStart,
                registerEnd
        );

        return new BigDecimal(retainedUsers * 100.0 / totalUsers)
                .setScale(2, RoundingMode.HALF_UP);
    }

    // 在UserStatsServiceImpl中添加
    private String getDateFormat(String timeRange) {
        return switch (timeRange.toLowerCase()) {
            case "year" -> "yyyy-MM";
            case "month", "quarter" -> "yyyy-MM-dd";
            default -> "MM-dd";
        };
    }

    private List<UserChartItem> fillEmptyDates(List<UserChartItem> items,
                                               TimeRange range,
                                               String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);

        // 生成日期范围序列
        List<LocalDate> dateRange = range.getStartTime().toLocalDate()
                .datesUntil(range.getEndTime().toLocalDate().plusDays(1))
                .collect(Collectors.toList());

        // 构建完整数据集
        return dateRange.stream()
                .map(date -> {
                    String key = date.format(formatter);
                    return items.stream()
                            .filter(item -> key.equals(item.getDateKey()))
                            .findFirst()
                            .orElse(new UserChartItem(key, 0, 0, 0));
                })
                .collect(Collectors.toList());
    }


}
